﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Windows;
using Microsoft.WindowsAPICodePack.Dialogs;
using System.Reflection;
using System.Timers;
using System.IO;
using System.Diagnostics;
using Microsoft.WindowsAPICodePack.Taskbar;
using System.Runtime.Remoting.Messaging;

namespace ArmoryViewer
{

    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    /// 
    public partial class App : Application
    {
        static string appVersion;
        bool done = false;
        bool updatecommand = false;
        static ProgressWindow pgs = new ProgressWindow();

        /// <summary>
        /// Gets a value indicating whether we are using Windows Vista.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if we are using Windows Vista; otherwise, <c>false</c>.
        /// </value>
		public static bool IsWindowsVista
		{
			get { return Environment.OSVersion.Version.Major >= 6; }
		}

        /// <summary>
        /// Gets the application version.
        /// </summary>
        /// <value>The application version.</value>
        public static string Version
        {
            get { return appVersion; }
        }

        /// <summary>
        /// Gets the current directory.
        /// </summary>
        /// <value>The current directory.</value>
        public static string CurrentDirectory
        {
            get { return AppDomain.CurrentDomain.BaseDirectory + Path.DirectorySeparatorChar; }
        }

        /// <summary>
        /// Shows the error dialog.
        /// </summary>
        /// <param name="exception">The exception.</param>
        public static void ShowErrorDialog(Exception exception)
        {
            ErrorWindow err = new ErrorWindow(exception);
        }

        private void Application_Startup(object sender, StartupEventArgs e)
        {
            Settings.Load();

            // Clean up my mess...
            if (File.Exists(CurrentDirectory + "updater.exe")) { File.Delete(CurrentDirectory + "updater.exe"); }
            if (File.Exists(CurrentDirectory + "aviewer.zip")) { File.Delete(CurrentDirectory + "aviewer.zip"); }
            if (File.Exists(CurrentDirectory + "aviewer.exe")) { File.Delete(CurrentDirectory + "aviewer.exe"); }
            if (File.Exists(CurrentDirectory + "7z.exe")) { File.Delete(CurrentDirectory + "7z.exe"); }
            
            // Set App Version
            appVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString();

            foreach (string arg in Environment.GetCommandLineArgs())
                ProcessCommand(arg);

            // Check for updates
            if (Settings.UpdateOnStartup && !updatecommand) CheckForUpdates();
        }

        public static void CheckForUpdates()
        {
            // Update is available, ask to update.
            if (Updater.UpdateAvailable)
            {
                if (App.IsWindowsVista)
                    try { ShowUpdateTaskDlg(); }
                    catch { ShowUpdatePrompt(); }
                else
                    ShowUpdatePrompt();
            }
        }

        static void ShowUpdateTaskDlg()
        {
            TaskDialog dlg = new TaskDialog();
            dlg.Caption = "Update Available";
            dlg.Icon = TaskDialogStandardIcon.Information;
            dlg.InstructionText = "An update is available, would you like to download it?";
            dlg.OwnerWindowHandle = Process.GetCurrentProcess().MainWindowHandle;
            dlg.StartupLocation = TaskDialogStartupLocation.CenterOwner;
            TaskDialogCommandLink yes = new TaskDialogCommandLink("yes", "Yes", "Downloads and install the update.") { Default = true, ShowElevationIcon = true };
            yes.Click += new EventHandler(yes_Click);
            TaskDialogCommandLink no = new TaskDialogCommandLink("no", "No", "Continue running Armory Viewer normally.");
            no.Click += delegate(object sender, EventArgs e)
            {
                dlg.Close();
            };
            dlg.Controls.Add(yes);
            dlg.Controls.Add(no);
            dlg.Show();
        }

        static void yes_Click(object sender, EventArgs e)
        {
            if (sender is TaskDialogCommandLink) { ((TaskDialog)(sender as TaskDialogCommandLink).HostingDialog).Close(); }
            Process proc = new Process();
            proc.StartInfo.FileName = System.Reflection.Assembly.GetExecutingAssembly().Location;
            proc.StartInfo.UseShellExecute = true;
            proc.StartInfo.Arguments = "/update";
            if (App.IsWindowsVista) proc.StartInfo.Verb = "runas";
            try { proc.Start(); }
            catch { return; }
            Application.Current.Shutdown();
        }

        static void ShowUpdatePrompt()
        {
            MessageBoxResult rslt = MessageBox.Show("An update is available, would you like to download it?", "Update Available", MessageBoxButton.YesNo, MessageBoxImage.Information, MessageBoxResult.No);
            if (rslt == MessageBoxResult.Yes) yes_Click(rslt, new EventArgs());
        }

        private void ProcessCommand(string arg)
        {
            switch (arg)
            {
                case "/update": Update(); updatecommand = true; return;
                default: break;
            }
        }

        private void Update()
        {
            Updater.UpdateProgressChanged += new Updater.UpdateProgressChangedEventHandler(Updater_UpdateProgressChanged);
            Updater.UpdateCompleted += new Updater.UpdateCompletedEventHandler(Updater_UpdateCompleted);
            pgs = new ProgressWindow();
            pgs.Caption = "Downloading Update";
            pgs.Text = "Determining what to do...";
            pgs.TaskDialogClosing += dlg_Closing;
            pgs.Closing += new System.ComponentModel.CancelEventHandler(pgs_Closing);

            Updater.DownloadUpdate();
            pgs.ShowMe();

            if (done) Application.Current.Shutdown();
        }



        /// <summary>
        /// Handles the UpdateCompleted event of the Updater control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        void Updater_UpdateCompleted(object sender, EventArgs e)
        {
            try
            {
                Process updater = new Process();
                updater.StartInfo.FileName = App.CurrentDirectory + "updater.exe";
                updater.StartInfo.CreateNoWindow = true;
                updater.Start();
                done = true;
                pgs.CloseDialog();
            }
            catch (Exception ex)
            {
                ShowErrorDialog(ex);
            }
        }

        void Updater_UpdateProgressChanged(object sender, UpdateProgressChangedEventArgs e)
        {
            pgs.CurrentValue = e.Progress;
            if (e.Message != null)
            {
                // Show error
                if (e.Message == "error")
                {
                    pgs.ProgressState = TaskDialogProgressBarState.Error;
                    pgs.Caption = "Update Failed";
                    pgs.Text = e.Error.Message;
                    pgs.StandardButtons = TaskDialogStandardButtons.Close;
                }
                // Show message
                else
                    pgs.Text = e.Message;
            }
        }

        bool Update_Closing()
        {
            if (pgs.StandardButtons == TaskDialogStandardButtons.Cancel && !done)
            {
                if (MessageBox.Show("Are you sure you wish to cancel the update?", "Armory Viewer", MessageBoxButton.YesNo) == MessageBoxResult.No)
                    return true;
                else
                    Updater.CancelUpdate();
            }
            return false;
        }

        void pgs_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            e.Cancel = Update_Closing();
        }
        
        void dlg_Closing(object sender, TaskDialogClosingEventArgs e)
        {
            e.Cancel = Update_Closing();
        }
    }
}
